package org.ponly.cta4j.drawing.text;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.font.TextAttribute;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.text.AttributedCharacterIterator;
import java.text.AttributedString;
import org.ponly.cta4j.drawing.color.ColorGenerator;
import org.ponly.cta4j.drawing.text.glyphsdecorator.GlyphsDecorator;
import org.ponly.cta4j.drawing.text.glyphsvisitor.GlyphsVisitor;
import org.ponly.cta4j.drawing.text.glyphsvisitor.HorizontalSpaceGlyphsVisitor;
import org.ponly.cta4j.drawing.text.glyphsvisitor.TranslateAllToRandomPointVisitor;

/**
 * 使用文本字形(glyph)绘制的笔刷.
 * <p>
 * 可以通过 {@link AttributedString} 设置更多的特效.
 * </p>
 *
 * @author vacoor
 * @since 1.0
 */
public class GlyphsBrush extends AbstractTextBrush {
    /**
     * 字形 visitors 用于控制字形的绘制位置.
     */
    private GlyphsVisitor[] glyphVisitors = new GlyphsVisitor[]{
            new HorizontalSpaceGlyphsVisitor(4),
            new TranslateAllToRandomPointVisitor()
    };

    /**
     * 字形 decorators 用于绘制字形的干扰信息.
     */
    private GlyphsDecorator[] glyphsDecorators;

    /* ************************************************
     *                CONSTRUCTOR
     * ************************************************/

    /**
     * 创建一个默认实例.
     */
    public GlyphsBrush() {
    }

    /**
     * 使用给定文本范围限定.
     *
     * @param acceptedMinLength 允许的最小文本长度
     * @param acceptedMaxLength 允许的最大文本长度
     */
    public GlyphsBrush(final int acceptedMinLength, final int acceptedMaxLength) {
        super(acceptedMinLength, acceptedMaxLength);
    }

    /**
     * 使用给定文本范围限定和给定文本颜色.
     *
     * @param acceptedMinLength 允许的最小文本长度
     * @param acceptedMaxLength 允许的最大文本长度
     * @param textColor         文本颜色
     */
    public GlyphsBrush(final int acceptedMinLength, final int acceptedMaxLength, final Color textColor) {
        super(acceptedMinLength, acceptedMaxLength, textColor);
    }

    /**
     * 使用给定文本范围限定和给定颜色生成器来生成文本颜色.
     *
     * @param acceptedMinLength 允许的最小文本长度
     * @param acceptedMaxLength 允许的最大文本长度
     * @param colorGenerator    文本颜色生成器
     */
    public GlyphsBrush(final int acceptedMinLength, final int acceptedMaxLength, final ColorGenerator colorGenerator) {
        super(acceptedMinLength, acceptedMaxLength, colorGenerator);
    }

    /**
     * 使用给定文本范围限定和给定颜色生成器来生成文本颜色, 并设置是否为每个字形生成颜色.
     *
     * @param acceptedMinLength   允许的最小文本长度
     * @param acceptedMaxLength   允许的最大文本长度
     * @param colorGenerator      文本颜色生成器
     * @param manageColorPerGlyph 是否为每个字形生成颜色
     */
    public GlyphsBrush(final int acceptedMinLength, final int acceptedMaxLength, final ColorGenerator colorGenerator,
                       final boolean manageColorPerGlyph) {
        super(acceptedMinLength, acceptedMaxLength, colorGenerator, manageColorPerGlyph);
    }

    /**
     * 使用给定文本范围限定, 字形 visitors.
     *
     * @param acceptedMinLength 允许的最小文本长度
     * @param acceptedMaxLength 允许的最大文本长度
     * @param glyphVisitors     字形 visitor 控制每个字形的绘制位置
     */
    public GlyphsBrush(final int acceptedMinLength, final int acceptedMaxLength, final GlyphsVisitor[] glyphVisitors) {
        super(acceptedMinLength, acceptedMaxLength);
        this.glyphVisitors = glyphVisitors.clone();
    }

    /**
     * 使用给定文本范围限定和给定文本颜色, 字形 visitors.
     *
     * @param acceptedMinLength 允许的最小文本长度
     * @param acceptedMaxLength 允许的最大文本长度
     * @param textColor         文本颜色
     * @param glyphVisitors     字形 visitor 控制每个字形的绘制位置
     */
    public GlyphsBrush(final int acceptedMinLength, final int acceptedMaxLength, final Color textColor,
                       final GlyphsVisitor[] glyphVisitors) {
        super(acceptedMinLength, acceptedMaxLength, textColor);
        this.glyphVisitors = glyphVisitors.clone();
    }

    /**
     * 使用给定文本范围限定和给定颜色生成器来生成文本颜色, 字形 visitors.
     *
     * @param acceptedMinLength 允许的最小文本长度
     * @param acceptedMaxLength 允许的最大文本长度
     * @param colorGenerator    文本颜色生成器
     * @param glyphVisitors     字形 visitor 控制每个字形的绘制位置
     */
    public GlyphsBrush(final int acceptedMinLength, final int acceptedMaxLength, final ColorGenerator colorGenerator,
                       final GlyphsVisitor[] glyphVisitors) {
        super(acceptedMinLength, acceptedMaxLength, colorGenerator);
        this.glyphVisitors = glyphVisitors.clone();
    }

    /**
     * 使用给定文本范围限定和给定颜色生成器来生成文本颜色, 字形 visitors.
     *
     * @param acceptedMinLength 允许的最小文本长度
     * @param acceptedMaxLength 允许的最大文本长度
     * @param colorGenerator    文本颜色生成器
     * @param glyphVisitors     字形 visitor 控制每个字形的绘制位置
     * @param glyphsDecorators  字形装饰
     */
    public GlyphsBrush(final int acceptedMinLength, final int acceptedMaxLength, final ColorGenerator colorGenerator,
                       final GlyphsVisitor[] glyphVisitors, final GlyphsDecorator[] glyphsDecorators) {
        super(acceptedMinLength, acceptedMaxLength, colorGenerator);
        this.glyphVisitors = glyphVisitors.clone();
        this.glyphsDecorators = glyphsDecorators.clone();
    }

    /**
     * 使用给定文本范围限定和给定颜色生成器来生成文本颜色, 并设置是否为每个字形生成颜色, 字形 visitors.
     *
     * @param acceptedMinLength   允许的最小文本长度
     * @param acceptedMaxLength   允许的最大文本长度
     * @param colorGenerator      文本颜色生成器
     * @param manageColorPerGlyph 是否为每个字形生成颜色
     * @param glyphVisitors       字形 visitor 控制每个字形的绘制位置
     */
    public GlyphsBrush(final int acceptedMinLength, final int acceptedMaxLength, final ColorGenerator colorGenerator,
                       final boolean manageColorPerGlyph, final GlyphsVisitor[] glyphVisitors) {
        super(acceptedMinLength, acceptedMaxLength, colorGenerator, manageColorPerGlyph);
        this.glyphVisitors = glyphVisitors.clone();
    }

    /**
     * 使用给定文本范围限定和给定颜色生成器来生成文本颜色, 并设置是否为每个字形生成颜色, 字形 visitors, 字形 decorators.
     *
     * @param acceptedMinLength   允许的最小文本长度
     * @param acceptedMaxLength   允许的最大文本长度
     * @param colorGenerator      文本颜色生成器
     * @param manageColorPerGlyph 是否为每个字形生成颜色
     * @param glyphVisitors       字形 visitor 控制每个字形的绘制位置
     * @param glyphsDecorators    字形的 decorator 绘制每个字形的装饰/干扰信息
     */
    public GlyphsBrush(final int acceptedMinLength, final int acceptedMaxLength,
                       final ColorGenerator colorGenerator, final boolean manageColorPerGlyph,
                       final GlyphsVisitor[] glyphVisitors, final GlyphsDecorator[] glyphsDecorators) {
        super(acceptedMinLength, acceptedMaxLength, colorGenerator, manageColorPerGlyph);
        this.glyphVisitors = glyphVisitors.clone();
        this.glyphsDecorators = glyphsDecorators.clone();
    }


    /* ************************************************
     *                METHODS
     * ************************************************/

    /**
     * {@inheritDoc}
     */
    @Override
    public BufferedImage draw(final BufferedImage canvas, final AttributedString attributedText) throws IllegalStateException {
        final Graphics2D g2d = canvas.createGraphics();
        final Rectangle2D bounds = new Rectangle2D.Float(0, 0, canvas.getWidth(), canvas.getHeight());
        final AttributedCharacterIterator it = attributedText.getIterator();

        // initialize color and hints
        g2d.setColor(getColor());
        customizeGraphicsRenderingHints(g2d);

        // build glyphs
        final Glyphs glyphs = new Glyphs();
        for (int i = 0; i < it.getEndIndex(); i++) {
            final Font font = (Font) it.getAttribute(TextAttribute.FONT);
            g2d.setFont(font);

            final FontRenderContext frc = g2d.getFontRenderContext();
            final GlyphVector glyph = font.createGlyphVector(frc, new char[]{it.current()});
            glyphs.addGlyphVector(glyph);
            it.next();
        }

        // before: visit
        if (null != glyphVisitors) {
            for (final GlyphsVisitor glyphVisitor : glyphVisitors) {
                glyphVisitor.visit(glyphs, bounds);
            }
        }

        /*
        double offsetX = 0;
        double offsetY = 0;
        double yRange = background.getHeight() - glyphs.getBoundsHeight();
        for (final int i = 0; i < glyphs.size(); i++) {
            offsetY = (yRange - glyphs.getBoundsY(i));
            if (0 < i) {
                offsetX = offsetX - glyphs.getBoundsX(i - 1) + glyphs.getBoundsWidth(i - 1);
            }

            GlyphVector v = glyphs.get(i);
            g2.drawGlyphVector(glyphs.get(i), (final int) offsetX, (final int) offsetY);

            if (isManageColorPerGlyph()) {
                g2.setColor(getColorGenerator().getColor());
            }
        }
        */

        // draw glyphs
        for (int i = 0; i < glyphs.size(); i++) {
            g2d.drawGlyphVector(glyphs.get(i), 0, 0);

            if (isManageColorPerGlyph()) {
                g2d.setColor(getColor());
            }
        }

        // after: decorate
        if (null != glyphsDecorators) {
            for (final GlyphsDecorator glyphsDecorator : glyphsDecorators) {
                glyphsDecorator.decorate(g2d, glyphs, canvas);
            }
        }

        g2d.dispose();
        return canvas;
    }

    /**
     * @return 当前实例使用 GlyphsVisitors.
     */
    public GlyphsVisitor[] getGlyphVisitors() {
        return glyphVisitors.clone();
    }

    /**
     * 设置当前实例使用 GlyphsVisitors.
     *
     * @param glyphVisitors GlyphsVisitors
     */
    public void setGlyphVisitors(final GlyphsVisitor[] glyphVisitors) {
        this.glyphVisitors = glyphVisitors.clone();
    }

    /**
     * @return 当前实例使用 GlyphsDecorators.
     */
    public GlyphsDecorator[] getGlyphsDecorators() {
        return glyphsDecorators.clone();
    }

    /**
     * 设置当前实例使用 GlyphsDecorators.
     *
     * @param glyphsDecorators GlyphsDecorators
     */
    public void setGlyphsDecorators(final GlyphsDecorator[] glyphsDecorators) {
        this.glyphsDecorators = glyphsDecorators.clone();
    }
}
